package controllers

import (
    "encoding/json"
    "github.com/beego/beego/v2/server/web"
    "github.com/beego/beego/v2/core/logs"
    "volux/models"
    "volux/utils"
    "volux/services"
    "fmt"
)

type BdevController struct {
    web.Controller
}

// @Summary 创建块设备
// @Description 创建新的后端存储设备
// @Tags Bdev
// @Accept json
// @Produce json
// @Param body body models.Bdev true "块设备信息"
// @Success 201 {object} models.Bdev
// @Failure 400 {object} utils.Error
// @Failure 409 {object} utils.Error
// @Router /bdevs [post]
func (c *BdevController) CreateBdev() {
    logs.Info("%s Received create bdev request", utils.LogBdev)
    
    // 增加日志记录请求头和请求体长度，帮助调试
    requestBody := c.Ctx.Input.RequestBody
    logs.Debug("%s Request body length: %d", utils.LogBdev, len(requestBody))
    logs.Debug("%s Headers: %+v", utils.LogBdev, c.Ctx.Input.Header)
    logs.Debug("%s Request body: %s", utils.LogBdev, string(requestBody))
    
    var bdev models.Bdev
    if err := json.Unmarshal(requestBody, &bdev); err != nil {
        logs.Error("%s Invalid request body: %v", utils.LogBdev, err)
        utils.ErrorResponse(c.Controller, 400, "Invalid request body")
        return
    }

    logs.Info("%s Creating bdev: %s (type: %s)", utils.LogBdev, bdev.Name, bdev.Type)
    
    // 获取资源锁
    lockService := services.NewLockService(utils.GetEtcdClient())
    if err := lockService.Lock(bdev.Name, 30); err != nil {
        logs.Error("%s Failed to acquire lock for bdev %s: %v", utils.LogBdev, bdev.Name, err)
        utils.ErrorResponse(c.Controller, 409, "Resource is locked")
        return
    }
    defer lockService.Unlock(bdev.Name)

    // 创建事务
    ts := services.NewTransactionService(c.Ctx.Request.Context())
    tx := ts.NewTransaction()

    // 添加SPDK操作
    spdkClient := utils.GetSPDKClient()
    tx.Add(
        func() error {
            switch (bdev.Type) {
            case "malloc":
                return spdkClient.CreateMallocBdev(bdev.Name, int(bdev.SizeMB)) // 显式类型转换
            case "aio":
                return spdkClient.CreateAioBdev(bdev.Name, bdev.Filename)
            case "nvme":
                return spdkClient.CreateNVMeBdev(bdev.Name, bdev.Traddr, bdev.Transport)
            default:
                return fmt.Errorf("unsupported bdev type: %s", bdev.Type)
            }
        },
        func() error {
            return spdkClient.DeleteBdev(bdev.Name)
        },
    )

    // 添加etcd操作
    storageService := services.NewStorageService(utils.GetEtcdClient())
    tx.Add(
        func() error {
            return storageService.StoreBdev(bdev)
        },
        func() error {
            return storageService.DeleteBdev(bdev.Name)
        },
    )

    // 执行事务
    if err := tx.Execute(); err != nil {
        utils.ErrorResponse(c.Controller, 500, "Failed to create bdev: "+err.Error())
        return
    }

    c.Ctx.Output.SetStatus(201)
    utils.SuccessResponse(c.Controller, bdev)
}

// DeleteVolume handles the deletion of a volume based on the provided ID.
// It retrieves the volume ID from the request, validates it, and attempts to
// create an SPDK client to perform the deletion. If the ID is missing or the
// SPDK client creation fails, it writes an appropriate error message to the response.
func (c *BdevController) DeleteBdev() {
    name := c.Ctx.Input.Param(":name")
    logs.Info("%s Received delete request for bdev: %s", utils.LogBdev, name)
    
    if name == "" {
        utils.ErrorResponse(c.Controller, 400, "Bdev name is required")
        return
    }

    spdkClient := utils.GetSPDKClient()
    if spdkClient == nil {
        utils.ErrorResponse(c.Controller, 500, "SPDK client not available")
        return
    }

    // 先从SPDK删除
    if err := spdkClient.DeleteBdev(name); err != nil {
        utils.ErrorResponse(c.Controller, 500, "Failed to delete bdev from SPDK")
        return
    }

    // 从etcd中删除
    storageService := services.NewStorageService(utils.GetEtcdClient())
    if err := storageService.DeleteBdev(name); err != nil {
        logs.Warning("Failed to delete bdev from etcd: %v", err)
    }

    c.Ctx.Output.SetStatus(200)
    utils.SuccessResponse(c.Controller, map[string]string{
        "message": "Bdev deleted successfully",
    })
}

// @Summary 获取所有块设备
// @Description 返回系统中所有配置的后端存储设备列表
// @Tags Bdev
// @Accept json
// @Produce json
// @Success 200 {array} models.Bdev
// @Failure 500 {object} utils.Error
// @Router /bdevs [get]
func (c *BdevController) GetBdevs() {
    client := utils.GetSPDKClient()
    if client == nil {
        c.Data["json"] = map[string]interface{}{
            "jsonrpc": "2.0",
            "id": 1,
            "result": []map[string]interface{}{},
        }
        c.Ctx.Output.SetStatus(500)
        c.ServeJSON()
        return
    }

    bdevs, err := client.GetBdevs()
    if err != nil {
        c.Data["json"] = map[string]interface{}{
            "jsonrpc": "2.0",
            "id": 1,
            "result": []map[string]interface{}{},
        }
        c.Ctx.Output.SetStatus(500)
        c.ServeJSON()
        return
    }

    // 确保返回空列表时也能正确展示
    if bdevs == nil {
        bdevs = []map[string]interface{}{}
    }

    c.Data["json"] = map[string]interface{}{
        "jsonrpc": "2.0",
        "id": 1,
        "result": bdevs,
    }
    c.Ctx.Output.SetStatus(200)
    c.ServeJSON()
}
